﻿using DevExpress.Mvvm;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Media;
using EduAssess.Models;
using EduAssess.Services;
using EduAssess.Views;

namespace EduAssess.ViewModels;

public class TestPageViewModel : BindableBase
{
    private readonly TestState _testState;
    private readonly PageNavigationService _navigationService;
    private readonly DialogService _dialogService;

    private Test? Test { get; }
    public int QuestionNumber => CurrentQuestionNumber + 1;
    private int CurrentQuestionNumber { get; set; }
    public Answer? CorrectAnswer { get; private set; }
    private bool IsEnabled { get; set; }
    public bool CanCheckAnswer { get; set; }
    public bool ShowPreviousButton { get; set; }
    private readonly List<Question> _questions;
    private bool _testCompleted;

    public Question CurrentQuestion => CurrentQuestionNumber >= _questions.Count()
        ? _questions.Last()
        : _questions[CurrentQuestionNumber];

    public TestPageViewModel(TestState testState, PageNavigationService navigationService,
        DialogService dialogService)
    {
        _testState = testState;
        _navigationService = navigationService;
        _dialogService = dialogService;
        Test = _testState.CurrentTest;
        CurrentQuestionNumber = 0;
        IsEnabled = true;
        CanCheckAnswer = _testState.CanCheckAnswer;
        ShowPreviousButton = !_testState.CanCheckAnswer;
        _questions = new List<Question>(Test!.Questions.Select(CopyQuestion));
    }

    public ICommand CheckAnswerCommand => new DelegateCommand(() =>
    {
        IsEnabled = false;
        var question = Test!.Questions.First(x => x.Id == CurrentQuestion.Id);

        CorrectAnswer = question.GetRightAnswer();

    }, () => CanCheckAnswer && IsEnabled && IsAnswerSelected());

    public ICommand NextQuestionCommand => new DelegateCommand(() =>
        {
            IsEnabled = true;
            var solidColorBrush = new SolidColorBrush(Colors.Black);
            if (solidColorBrush == null) throw new ArgumentNullException(nameof(solidColorBrush));
            CorrectAnswer = null;

            if (CurrentQuestionNumber >= Test!.QuestionCount - 1 && !_testCompleted)
            {
                if (CanCheckAnswer) IsEnabled = false;

                _testCompleted = true;
                _dialogService.ShowMessage("Тест завершен, посмотрите результаты!");
            }

            if (CurrentQuestionNumber < Test.QuestionCount - 1)
                CurrentQuestionNumber++;

        },
        () => Test != null && IsAnswerSelected() &&
              !(_testCompleted && CurrentQuestionNumber >= Test.QuestionCount - 1));

    public ICommand PreviousQuestionCommand => new DelegateCommand(() =>
    {
        IsEnabled = true;
        CorrectAnswer = null;
        CurrentQuestionNumber--;
    }, () => CurrentQuestionNumber > 0);

    public ICommand ShowResultsCommand => new DelegateCommand(() =>
    {
        CheckResult();
        _navigationService.Navigate(new StatisticsPage());
    }, () => _testCompleted);

    public ICommand LeaveTestCommand =>
        new DelegateCommand(() => { _navigationService.GoBack(); }, () => _testCompleted);

    private static Question CopyQuestion(Question q)
    {
        var res = new Question
        {
            Id = q.Id,
            Name = q.Name,
            Answers = new ObservableCollection<Answer>()
        };

        foreach (var item in q.Answers)
        {
            res.Answers.Add(new Answer
            {
                Id = item.Id,
                Name = item.Name,
                IsTrue = false,
            });
        }

        return res;
    }

    private bool Check(Question q)
    {
        var question = Test!.Questions.First(x => x.Id == q.Id);

        var isCorrect = question.CheckAnswer(q);

        return isCorrect;
    }

    private bool IsAnswerSelected()
        => CurrentQuestion.Answers.Any(item => item.IsTrue);

    private void CheckResult()
    {
        _testState.RightAnswers.Clear();
        _testState.WrongAnswers.Clear();
        foreach (var question in _questions)
        {
            if (Check(question)) _testState.RightAnswers.Add(question);
            else _testState.WrongAnswers.Add(question);
        }
    }
}